package com.plumejob.executor;

import com.plumejob.executor.annotation.PlumeJob;
import com.plumejob.executor.util.ClassFindUtil;
import com.plumejob.executor.util.HttpsClient;
import com.plumejob.executor.util.IpUtils;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author : pdl
 * @date : 2021/2/5 17:56
 */
public class PlumejobContext {

    private static Logger logger = LoggerFactory.getLogger(PlumejobContext.class);

    private static StdSchedulerFactory schedulerFactory;

    private static Map<String, PlumejobDetail> jobDetailMap = new ConcurrentHashMap<>();

    public static String appName;
    public static String host;

    public static volatile int isMaster = 0;


    public static void init(String appName, String host, Integer poolSize) throws SchedulerException {
        PlumejobContext.appName = appName;
        PlumejobContext.host = host;
        schedulerFactory = new StdSchedulerFactory();
        Properties properties = new Properties();
        properties.setProperty("org.quartz.threadPool.threadCount", poolSize.toString());
        schedulerFactory.initialize(properties);
    }

    public static boolean runJob(PlumejobDetail job) throws SchedulerException {
        if (validJobDetail(job)) {
            Scheduler scheduler = schedulerFactory.getScheduler();
            JobDetail jobDetail = JobBuilder.newJob(Plumejob.class)
                    .withIdentity(job.getJobName(), job.getAppName()).build();

            Trigger trigger = TriggerBuilder.newTrigger().startNow()
                    .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpr()))
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);

            job.setCronTrigger(trigger);
            job.setScheduler(scheduler);
            logger.info("start job : {}", job.getJobName());
            job.getScheduler().start();
            job.setRunning(1);
            jobDetailMap.put(job.getJobName(), job);
            return true;
        }
        return false;
    }

    public static void start(String basePackages) throws SchedulerException {
        //心跳
        Scheduler scheduler = schedulerFactory.getScheduler();
        JobDetail jobDetail = JobBuilder.newJob(HeartBeatjob.class)
                .withIdentity("plume_heart_beat_job", "plume_sync").build();

        Trigger trigger = TriggerBuilder.newTrigger().startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
                .build();
        scheduler.scheduleJob(jobDetail, trigger);

        //扫描任务进行注册
        if (basePackages != null) {
            String packages = basePackages.trim();
            List<PlumejobDetail> autoRegisterJobList = new ArrayList<>();
            try {
                List<Class<?>> classes = ClassFindUtil.getClasses(packages);
                for (Class<?> c : classes) {
                    Method m[] = c.getDeclaredMethods();
                    for (int i = 0; i < m.length; i++) {
                        Method method = m[i];
                        if (method.isAnnotationPresent(PlumeJob.class)) {
                            PlumeJob annotation = method.getAnnotation(PlumeJob.class);
                            PlumejobDetail jd = new PlumejobDetail();
                            jd.setAppName(PlumejobContext.appName);
                            String jobName = annotation.jobName();
                            if ("".equals(jobName)) {
                                jobName = method.getName();
                            }
                            jd.setJobName(jobName);
                            jd.setJobClass(c.getName());
                            jd.setJobMethod(method.getName());
                            jd.setCronExpr(annotation.cron());
                            jd.setAddress(IpUtils.getIp());
                            jd.setType(2);
                            autoRegisterJobList.add(jd);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (!autoRegisterJobList.isEmpty()) {
                HttpsClient.post(PlumejobContext.host + "/plumejob/register", autoRegisterJobList);
            }
        }

        //同步任务
        JobDetail SyncJobDetail = JobBuilder.newJob(Syncjob.class)
                .withIdentity("plume_sync_job", "plume_sync").build();

        Trigger syncJobTrigger = TriggerBuilder.newTrigger().startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())
                .build();
        scheduler.scheduleJob(SyncJobDetail, syncJobTrigger);

        scheduler.start();
    }

    public static PlumejobDetail getJobDetailByName(String jobName) {
        return jobDetailMap.get(jobName);
    }

    private static boolean validJobDetail(PlumejobDetail jobDetail) {
        if (jobDetail.getAppName() != null && jobDetail.getJobName() != null && jobDetail.getJobClass() != null
                && !(jobDetail.getJobMethod() == null | jobDetail.getCronExpr() == null)) {
            return true;
        }
        return false;
    }

    public static void remove(PlumejobDetail job) throws SchedulerException {
        if (job == null) {
            return;
        }
        job.getScheduler().shutdown();
        jobDetailMap.remove(job.getJobName());
    }
}
